# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/12 15:38:36-07:00 yanmin.zhang@intel.com # [IA64] clean up ptrace corner cases # # Patch from yanmin.zhang@intel.com to fix up some corner cases # in ptrace. Many thanks to davidm for reviewing and improving. # # Backported to 2.4 by Bjorn Helgaas (bjorn.helgaas@hp.com). # # arch/ia64/kernel/process.c # 2005/03/12 15:24:43-07:00 yanmin.zhang@intel.com +1 -1 # clean up ptrace corner cases # # arch/ia64/kernel/ivt.S # 2005/03/12 15:24:43-07:00 yanmin.zhang@intel.com +25 -22 # clean up ptrace corner cases # # arch/ia64/kernel/entry.S # 2005/03/12 15:24:43-07:00 yanmin.zhang@intel.com +19 -7 # clean up ptrace corner cases # diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S 2005-03-12 15:59:49 -08:00 +++ b/arch/ia64/kernel/entry.S 2005-03-12 15:59:49 -08:00 @@ -49,8 +49,11 @@ * setup a null register window frame. */ ENTRY(ia64_execve) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3) - alloc loc1=ar.pfs,3,2,4,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,4,0 /* Leave from kernel and restore all pt_regs to correspending registers. This is special * because ia32 application needs scratch registers after return from execve. */ @@ -94,8 +97,11 @@ END(ia64_execve) GLOBAL_ENTRY(sys_clone2) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) - alloc r16=ar.pfs,3,2,4,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc r16=ar.pfs,8,2,4,0 DO_SAVE_SWITCH_STACK mov loc0=rp mov loc1=r16 // save ar.pfs across do_fork @@ -113,8 +119,11 @@ END(sys_clone2) GLOBAL_ENTRY(sys_clone) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) - alloc r16=ar.pfs,2,2,4,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc r16=ar.pfs,8,2,4,0 DO_SAVE_SWITCH_STACK mov loc0=rp mov loc1=r16 // save ar.pfs across do_fork @@ -1091,7 +1100,10 @@ ENTRY(sys_rt_sigreturn) PT_REGS_UNWIND_INFO(0) - alloc r2=ar.pfs,0,0,1,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + alloc r2=ar.pfs,8,0,1,0 .prologue PT_REGS_SAVES(16) adds sp=-16,sp diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S --- a/arch/ia64/kernel/ivt.S 2005-03-12 15:59:49 -08:00 +++ b/arch/ia64/kernel/ivt.S 2005-03-12 15:59:49 -08:00 @@ -48,6 +48,7 @@ #include #include #include +#include #if 1 # define PSR_DEFAULT_BITS psr.ac @@ -678,15 +679,29 @@ mov r1=IA64_KR(CURRENT); /* r1 = current (physical) */ ;; invala; + + /* adjust return address so we skip over the break instruction: */ + + extr.u r8=r29,41,2 // extract ei field from cr.ipsr extr.u r16=r29,32,2; /* extract psr.cpl */ ;; + cmp.eq p6,p7=2,r8 // isr.ei==2? cmp.eq pKern,pUser=r0,r16; /* are we in kernel mode already? (psr.cpl==0) */ - /* switch from user to kernel RBS: */ ;; +(p6) mov r8=0 // clear ei to 0 +(p6) adds r28=16,r28 // switch cr.iip to next bundle cr.ipsr.ei wrapped +(p7) adds r8=1,r8 // increment ei to next slot + ;; + dep r29=r8,r29,41,2 // insert new ei into cr.ipsr + ;; + + /* switch from user to kernel RBS: */ mov r30=r0 MINSTATE_START_SAVE_MIN_VIRT br.call.sptk.many b7=ia64_syscall_setup ;; + // p10==true means out registers are more than 8 or r15's Nat is true +(p10) br.cond.spnt.many ia64_ret_from_syscall mov r3=255 adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024 adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = ¤t->ptrace @@ -704,28 +719,9 @@ ld8 r2=[r2] // r2 = current->ptrace mov b6=r16 - // arrange things so we skip over break instruction when returning: - - adds r16=PT(CR_IPSR)+16,sp // get pointer to cr_ipsr - adds r17=PT(CR_IIP)+16,sp // get pointer to cr_iip ;; - ld8 r18=[r16] // fetch cr_ipsr tbit.z p8,p0=r2,PT_TRACESYS_BIT // (current->ptrace & PF_TRACESYS) == 0? ;; - ld8 r19=[r17] // fetch cr_iip - extr.u r20=r18,41,2 // extract ei field - ;; - cmp.eq p6,p7=2,r20 // isr.ei==2? - adds r19=16,r19 // compute address of next bundle - ;; -(p6) mov r20=0 // clear ei to 0 -(p7) adds r20=1,r20 // increment ei to next slot - ;; -(p6) st8 [r17]=r19 // store new cr.iip if cr.isr.ei wrapped around - dep r18=r20,r18,41,2 // insert new ei into cr.isr - ;; - st8 [r16]=r18 // store new value for cr.isr - (p8) br.call.sptk.many b6=b6 // ignore this return addr br.cond.sptk ia64_trace_syscall @@ -807,8 +803,11 @@ * - psr.ic enabled, interrupts restored * - r1: kernel's gp * - r3: preserved (same as on entry) + * - r8: -EINVAL if p10 is true * - r12: points to kernel stack * - r13: points to current task + * - p10: TRUE if syscall is invoked with more than 8 out + * registers or r15's Nat is true * - p15: TRUE if interrupts need to be re-enabled * - ar.fpsr: set to kernel settings */ @@ -825,12 +824,15 @@ st8 [r17]=r28,16; /* save cr.iip */ mov r28=b0; (pKern) mov r18=r0; /* make sure r18 isn't NaT */ + extr.u r11=r19,7,7 /* get sol of ar.pfs */ + and r8=0x7f,r19 /* get sof of ar.pfs */ ;; (p9) mov in1=-1 tnat.nz p10,p0=in2 st8 [r16]=r30,16; /* save cr.ifs */ st8 [r17]=r25,16; /* save ar.unat */ (pUser) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ + add r11=8,r11 ;; st8 [r16]=r26,16; /* save ar.pfs */ st8 [r17]=r27,16; /* save ar.rsc */ @@ -870,12 +872,13 @@ .mem.offset 8,0; st8.spill [r17]=r15,16; adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ ;; + cmp.lt p10,p9=r11,r8 /* frame size can't be more than local+8 */ mov r13=IA64_KR(CURRENT); /* establish `current' */ movl r1=__gp; /* establish kernel global pointer */ ;; MINSTATE_END_SAVE_MIN_VIRT - tnat.nz p9,p0=r15 +(p9) tnat.nz p10,p0=r15 (p8) mov in7=-1 ssm psr.ic | PSR_DEFAULT_BITS movl r17=FPSR_DEFAULT @@ -883,10 +886,10 @@ ;; srlz.i // guarantee that interruption collection is on cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 -(p9) mov r15=-1 (p15) ssm psr.i // restore psr.i mov.m ar.fpsr=r17 stf8 [r8]=f1 // ensure pt_regs.r8 != 0 (see handle_syscall_error) +(p10) mov r8=-EINVAL br.ret.sptk.many b7 END(ia64_syscall_setup) diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c 2005-03-12 15:59:49 -08:00 +++ b/arch/ia64/kernel/process.c 2005-03-12 15:59:49 -08:00 @@ -485,7 +485,7 @@ return 1; /* f0-f31 are always valid so we always return 1 */ } -asmlinkage long +long sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs) { int error;